import cherrypy
import sqlite3
import Common
import os
import time
import hashlib

from postmarkup import render_bbcode

localdir = os.path.dirname(__file__)
absdir = os.path.join(os.getcwd(), localdir)


class User(Common.Template):

	def index (self):
		return self.default()
	index.exposed = True
	
	# this function receives post data from the register page. at this point we already know the username is unique. all we do here is add the user to the db and set the user's session. we then display the /User index
	def user_register(self, Username=None, Password=None, Avatar=None, Signature=None):
		c = cherrypy.thread_data.db.cursor()
		c.execute('select max(ID) from User')
		uid = c.fetchone()[0] + 1
		# add the user to the system
		c.execute('insert into User (ID,Username,Password,Permission,Avatar,Signature,JoinDate) values (NULL,?,?,2,?,?, date(\'now\'))', (self.strip_html_bbcode(Username), hashlib.md5(Password).hexdigest(), str(self.upload(Avatar, uid)), Signature,))
		cherrypy.thread_data.db.commit()
		# create the user's session
		cherrypy.session['ID'] = uid
		cherrypy.session['Username'] = self.strip_html_bbcode(Username)
		cherrypy.session['Permission'] = c.execute('select Permission from User where ID=?', (uid,)).fetchone()[0]
		return self.index()
	user_register.exposed = True
	

	#this page displays the registration form on the /login page after the user hits the register button. the post information is directed here and put in its respective fields. the form itself posts to user_register
	def registerUserPage(self, user, passwd):
		cursor = cherrypy.thread_data.db.cursor()
		yield self.header()
		yield self.links()
		yield "<h1>Registration:</h1>"
		yield "<table class='registration' width='100%'>"
		#selects the admin which will always be there
		cursor.execute("SELECT * FROM User WHERE ID IS 0")
		info = cursor.fetchone()
		#grabs a list of all column names
		attr = cursor.description
		yield "<form method='post' action='User/user_register' enctype='multipart/form-data'>"
		#loop through all 8 columns
		for i in range(8):
			attrTmp = attr[i]
			yield "<tr>"
			#horrific if/else block for the register form. basically makes a row for each column and selectively lets the user edit them.
			if not (attrTmp[0]=='ID' or attrTmp[0]=='BanTimestamp' or attrTmp[0]=='Permission' or attrTmp[0]=='JoinDate'):
				yield "<td class='registration_list'>%s</td>"%str(attrTmp[0])
				yield "<td class='registration_list_edit'>"
				if attrTmp[0]=='Password':
					yield "<input name='%s' type='password' value='%s' readonly></input>"%(attrTmp[0],str(passwd))
				elif attrTmp[0]=='Avatar':
					yield "<input name='%s' type='file'></input>"%attrTmp[0]
				elif attrTmp[0]=='Username':
					yield "<input name='%s' type='text' value='%s' readonly></input>"%(attrTmp[0],str(user))
				elif attrTmp[0]=='Signature':
					yield "<textarea class='monospace' name='Signature' rows='20' cols='80'>Signature</textarea>"
				yield "</td>"
				yield "</tr>"
		yield "<tr><td class='registration_list'><input type='submit' value='Register'></input>"
		yield "</form>"
		yield "</table>"
		yield "<br />"+self.footer()
	registerUserPage.exposed = True
		
	# simple method to determine if you can edit userinfo
	def ownpage (self, id):
		if self.getLoginPermission() == 0 or id == self.getLoginID() or ( self.getLoginPermission() == 1 and id != 0 ) or ( self.getLoginPermission() == 0 and id == 0 ):
			return True
		else:
			return False

	def upload (self, image=None, id=None):
		#because image is still an object even if nothing is uploaded this is the only way i could find to determine if nothing was uploaded. seems like there should be an easier way to do this...
		if image.fullvalue()=="":
			#reutrn empty string so it doesnt break all avatar pics in the forum
			return ""
		saved_image = open('images/avatars/%s.dat'%id, 'wb')
		while True:
			#write pic file in 512bit(byte?) chunks
			data = image.file.read(512)
			if not data:
				break
			saved_image.write(data)
		saved_image.close()
		return saved_image.name

	def user_edit (self, Username=None, Permission=None, BanTimestamp=None, Avatar=None, Password=None, ID = None, JoinDate = None, Signature = None):
		c = cherrypy.thread_data.db.cursor()
		#somewhat better if block than the register form. if a value was entered, change it in the db.
		if Password:
			c.execute("UPDATE User SET Password=? WHERE ID=?",(hashlib.md5(Password).hexdigest(), int(ID),))
			cherrypy.thread_data.db.commit()
		#would probably work fine with just the fullvalue()==""
		if Avatar and (not Avatar.fullvalue() == ""):
			Av = self.upload(Avatar, ID)
			c.execute("UPDATE User Set Avatar=? WHERE ID=?",(Av,int(ID),))
			cherrypy.thread_data.db.commit()
		if Permission and self.getLoginPermission() < 1:
			c.execute("UPDATE User Set Permission=? WHERE ID=?",(Permission,int(ID),))
			cherrypy.thread_data.db.commit()
		if BanTimestamp and self.getLoginPermission() < 2:
			#parse correct timestamp
			ts = int(BanTimestamp)
			if ts < 0:
				ts = "NULL"
			elif ts > 0:
				ts = time.time() + ts * 24 * 60 * 60
			c.execute("UPDATE User Set BanTimestamp=? WHERE ID=?",(ts,int(ID),))
			cherrypy.thread_data.db.commit()
		if Signature:
			c.execute("UPDATE User Set Signature=? WHERE ID=?",(Signature,int(ID),))
			cherrypy.thread_data.db.commit()
		yield self.redirect("/User/%s"%ID)
	user_edit.exposed = True

	#should be -1 by default to indicate something went wrong if its not changed
	def default (self, id = -1):
		# for some reason id is passed as a string
		id = int(id)
		cursor = cherrypy.thread_data.db.cursor()
		cursor2 = cherrypy.thread_data.db.cursor()
		yield self.header()
		yield self.links()
		# i dont think i need breadcrumbs in this pageview
		yield self.breadcrumbs()
		yield "<br/>"

		# if the user is looking at the root Users page, display list of all + links
		if id == -1:
			cursor.execute('''
				SELECT User.ID, User.Username, User.Avatar, User.Joindate, User.Signature
				FROM User''')
						
			#print list of all users
			yield "<table class='user_list' align='center' width='100%'>"
			yield "<tr><th class='user_list' width='200px'>Username</th><th class='user_list' width='125px'>Avatar</th><th class='user_list' width='125px'>Post Count</th><th class='user_list' width='125px'>Join Date</th><th class='user_list'>Signature</th></tr>"
			#select number of posts by UserID
			for UserID, Username, Avatar, Joindate, Signature in cursor.fetchall():
				cursor2.execute('''SELECT COUNT(Post.ID) FROM Post WHERE Post.UserID = ?''', (UserID,))
				count = cursor2.fetchone()[0]
				
				if Avatar == "" or Avatar == None:
					yield "<tr align='center'><td class='user_list'><a href='%s'>%s</a></td><td class='user_list'><td class='user_list'>%s</td><td class='user_list'>%s</td><td class='user_list'>%s</td></tr>" % (UserID, Username, count, Joindate, render_bbcode(Signature))
				else:
					yield "<tr align='center' valign='center'><td class='user_list'><a href='%s'>%s</a></td><td class='user_list'><img src='/%s' width='100px' height='100px' /></td><td class='user_list'>%s</td><td class='user_list'>%s</td><td class='user_list'>%s</td></tr>" % (UserID, Username, Avatar, count, Joindate, render_bbcode(Signature))
			yield "</table>"

		else:
			#print all the user info for a given user
			yield "<br /><h1>%s's User Info</h1><br />"%self.getUsername(id)
			yield "<table class='user_info' width='100%'>"
			cursor.execute("SELECT * FROM User WHERE ID IS ?",(id,))
			info = cursor.fetchone()
			attr = cursor.description
			yield "<form method='post' action='user_edit' enctype='multipart/form-data'>"
			#loop like the other loops through all columns in the user table
			for i in range(8):
				attrTmp = attr[i]
				yield "<tr>"
				#someone elses page
				if attrTmp[0] != 'Password' or self.ownpage(id):
					yield "<td class='user_info_list'>%s</td>"%str(attrTmp[0])
					if attrTmp[0]=='BanTimestamp' and info[i] != None and info[i] != "NULL":
						# decode the timestamp
						yield "<td class='user_info_list'>%s</td>"%str(time.ctime(int(info[i])))
					elif attrTmp[0]=="Password":
						yield "<td class='user_info_list'>&nbsp;</td>"
					else:
						yield "<td class='user_info_list'>%s</td>"%render_bbcode(str(info[i]))
				if self.ownpage(id):
					yield "<td class='user_info_list_edit'>"
					if attrTmp[0]=='Password':
						yield "<input name='%s' "%attrTmp[0]
						yield "type='password'>"
					elif attrTmp[0]=='JoinDate':
						yield "<input name='%s' "%attrTmp[0]
						yield "type='hidden' readonly>"
					elif attrTmp[0]=='Avatar':
						yield "<input name='%s' "%attrTmp[0]
						yield "type='file'>"
					elif attrTmp[0]=='ID':
						yield "<input name='%s' "%attrTmp[0]
						yield "type='hidden' value='%s' readonly>"%id
					elif attrTmp[0]=='Signature':
						yield "<textarea class='monospace' name='%s' rows='20' cols='80'>%s</textarea>" % (attrTmp[0], info[i])
					elif attrTmp[0]=='Username':
						yield "<input name='%s' "%attrTmp[0]
						yield "type='hidden' value='%s' readonly>"%str(info[i])
					#mod/admin editable stuff below
					elif attrTmp[0]=='BanTimestamp':
						if self.getLoginPermission() < 2 and id != self.getLoginID():
							yield "<input name='%s' "%attrTmp[0]
							yield "type='text'> <i>(offest in days, 0 == permaban, -1 == clear)</i>"
						else:
							yield "<input name='%s' "%attrTmp[0]
							yield "type='hidden' readonly>"
					elif attrTmp[0]=='Permission':
						if self.getLoginPermission() < 1:
							yield "<input name='%s' "%attrTmp[0]	
							yield "type='text'>"
						else:
							yield "<input name='%s' "%attrTmp[0]
							yield "type='hidden' readonly>"
					yield "</input></td>"
				yield "</tr>"
			# now print all your info
			yield "<tr><td class='user_info_list'>"
			# display submit button only if the user has permission to
			if self.ownpage(id):
				yield "<input type='submit' value='Submit Changes'></input>"
			yield "</form>"
			yield "</table>"

		yield "<br />"+self.footer()

	default.exposed = True
